home *** CD-ROM | disk | FTP | other *** search
- /*{{{}}}*/
- /*{{{ #includes*/
- #ifdef CONFIG_H
- # include "config.h"
- #endif
-
- #include <sys/types.h>
- #include <unistd.h>
- #ifdef TERMINFO
- # ifdef INC_CURSES
- # include <curses.h>
- # endif
- # ifdef INC_TERM
- # include <term.h>
- # endif
- # define TERM_DATA_BASE "terminfo"
- #else
- # include <termcap.h>
- # define TERM_DATA_BASE "termcap"
- #endif
- #ifdef TIOCGWINSZ
- # include <sys/ioctl.h>
- #endif
- #include <termios.h>
- #include <limits.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
-
- #define SCREEN_C
- #define I_BUFFLOOP_C
- #define I_DISPLAY_C
- #define I_GETMSG_C
- #define I_GETTK_C
- #define I_KEYBOARD_C
- #define I_MAIN_C
- #define I_MESSAGES_C
- #define I_SIGNALS_C
-
- #include "exit.h"
- #include "origami.h"
- #include <h/envvar_str.h>
- /*}}} */
-
- /*{{{ variable declarations*/
- private boolean so_active=False;
- private boolean so_wished=False;
- public char const *terminal=0;
- /*{{{ termcap data*/
- /*{{{ needed capabilities*/
- private char const *term_do_cm;
- private char const *term_do_ho;
- private char const *term_do_do;
- private char const *term_do_n_do;
- private char const *term_do_ri;
- private char const *term_do_n_ri;
- /*}}} */
- /*{{{ optional*/
- private char const *term_do_ti;
- private char const *term_do_te;
- private char const *term_do_ks;
- private char const *term_do_ke;
- private char const *term_do_cd;
- private char const *term_do_cl;
- public char const *ce;
- private char const *term_do_n_ic;
- private char const *term_do_n_dc;
- public char const *al;
- public char const *dl;
- private char const *do_AL;
- private char const *do_DL;
- private char const *term_do_bl;
- private char const *term_do_vb;
- private char const *term_do_se;
- public char const *so;
- private char const *term_do_rp;
- #ifdef USE_SCRBUFF
- # ifndef BLOCK_FLUSH
- private char const *term_do_im;
- private char const *term_do_ic;
- private char const *term_do_ip;
- private char const *term_do_ei;
- private char const *term_do_dc;
- private char const *term_do_le;
- private char const *term_do_LE;
- private char const *term_do_up;
- private char const *term_do_n_up;
- public boolean mi;
- # endif
- private char const *term_do_vi;
- private char const *term_do_vs;
- #endif
- public boolean am,hz,xs,xt;
- public int sg;
- /*}}} */
- /*}}} */
- #if defined(USE_SCRBUFF) && !defined(BLOCK_FLUSH)
- public boolean use_shift;
- #endif
- public FILE *scrout;
- public win_data screen;
- /*}}} */
-
- /*{{{ t_param_1,t_param_2*/
- #ifdef TERMINFO
- # define USE_TPARM
- #endif
- #ifdef USE_TPARM
- # ifdef TPARM_NEEDS_2
- # define t_param_1(f,x1) (f?(char*)tparm(f,x1,0):(char*)0)
- # else
- # define t_param_1(f,x1) (f?(char*)tparm(f,x1):(char*)0)
- #endif
- # define t_param_2(f,x1,x2) (f?(char*)tparm(f,x1,x2):(char*)0)
- #else
- private char *tg_res;
- # define t_goto(f,x1,x2) (strcmp(tg_res=tgoto(f,x1,x2),"OOPS")?tg_res:(char*)0)
- # define t_param_1(f,x1) (f?(char*)t_goto(f,0,x1):(char*)0)
- # define t_param_2(f,x1,x2) (f?(char*)t_goto(f,x2,x1):(char*)0)
- #endif
- /*}}} */
- /*{{{ outchar*/
- private int outchar(int ch)
- {
- if (scrout) oputc(ch);
- return(ch);
- }
- /*}}} */
- /*{{{ move_cursor_to*/
- public void move_cursor_to(int y,int x)
- {
- if (scrout)
- if (y==1 && x==1 && term_do_ho)
- tputs(term_do_ho,1,outchar);
- else if (term_do_cm)
- /*{{{ use term_do_cm*/
- { char const *s;
-
- if ((s=t_param_2(term_do_cm,y-1,x-1))==0)
- exit(r_init_err);
- tputs(s,1,outchar);
- }
- /*}}} */
- else
- /*{{{ step by step*/
- { char const *s;
-
- tputs(term_do_ho,1,outchar);
- if (--y>0)
- if ((s=t_param_1(term_do_n_do,y)))
- tputs(s,1,outchar);
- else if (term_do_do)
- do tputs(term_do_do,1,outchar); while (--y);
- else
- exit(r_init_err);
- if (--x>0)
- if ((s=t_param_1(term_do_n_ri,x)))
- tputs(s,1,outchar);
- else if (term_do_ri)
- do tputs(term_do_ri,1,outchar); while (--x);
- else
- exit(r_init_err);
- }
- /*}}} */
- }
- /*}}} */
- /*{{{ insLine: if al known, do and return False, else do nothing and return True*/
- public boolean insLine(int n)
- {
- if (scrout)
- {
- #if defined(USE_SCRBUFF) && !defined(BLOCK_FLUSH)
- char const *s;
-
- if (n>1 && (s=t_param_1(do_AL,n)))
- tputs(s,1,outchar);
- else
- #endif
- if (al)
- while (n-->0)
- tputs(al,1,outchar);
- else
- return(True);
- }
-
- return(False);
- }
- /*}}} */
- /*{{{ DelLine: if dl known, do and return False, else do nothing and return True*/
- public boolean DelLine(int n)
- {
- if (scrout)
- {
- #if defined(USE_SCRBUFF) && !defined(BLOCK_FLUSH)
- char const *s;
-
- if (n>1 && (s=t_param_1(do_DL,n)))
- tputs(s,1,outchar);
- else
- #endif
- if (dl)
- while (n-->0)
- tputs(dl,1,outchar);
- else
- return(True);
- }
-
- return(False);
- }
- /*}}} */
- #ifdef USE_SCRBUFF
- # ifndef BLOCK_FLUSH
- /*{{{ step_or_move_cursor*/
- public void step_or_move_cursor(int y, int x, int dy, int dx)
- {
- if (dx || dy)
- { char const *s;
-
- if
- /*{{{ both diff or no valid capability given*/
- ( (dx&&dy)
- || (dx==1 && (s=term_do_ri)==0)
- || (dx>0 && (s=t_param_1(term_do_n_ri,dx))==0)
- || (dx==-1 && (s=term_do_le)==0)
- || (dx<0 && (s=t_param_1(term_do_LE,-dx))==0)
- || (dy==1 && (s=term_do_do)==0)
- || (dy>0 && (s=t_param_1(term_do_n_do,dy))==0)
- || (dy==-1 && (s=term_do_up)==0)
- || (dy<0 && (s=t_param_1(term_do_n_up,-dy))==0)
- )
- /*}}} */
- move_cursor_to(y,x);
- else
- tputs(s,1,outchar);
- }
- }
- /*}}} */
- /*{{{ insChar: return true, if not possible*/
- public void insChar(unsigned char *s,int l)
- {
- if (term_do_im || term_do_ic)
- { if (l)
- { if (term_do_im) tputs(term_do_im,1,outchar);
- do
- { if (term_do_ic) tputs(term_do_ic,1,outchar);
- oputc(*s);
- s++;
- if (term_do_ip) tputs(term_do_ip,1,outchar);
- }
- while (--l);
- if (term_do_ei) tputs(term_do_ei,1,outchar);
- }
- }
- }
- /*}}} */
- /*{{{ delChar: return True, if not possible*/
- public void delChar(int n)
- {
- if (term_do_dc || term_do_n_dc)
- { char *s;
-
- if (n)
- if ((n>1 || !term_do_dc) && (s=t_param_1(term_do_n_dc,n)))
- tputs(s,1,outchar);
- else
- do
- tputs(term_do_dc,1,outchar);
- while (--n);
- }
- }
- /*}}} */
- # endif
- /*{{{ cursor*/
- public void scr_cursor(boolean show)
- {
- char const *s;
-
- s=show?term_do_vs:term_do_vi;
- if (s)
- tputs(s,1,outchar);
- }
- /*}}} */
- #endif
- /*{{{ moputc*/
- #ifdef BLOCK_FLUSH
- private
- #else
- public
- #endif
- int moputc(int c,int n)
- {
- if (scrout)
- if (n>0)
- { char *s;
-
- if ((n>M_RP_LIMIT) && (s=t_param_2(term_do_rp,(int)c,n)))
- tputs(s,1,outchar);
- else
- if
- ( !so_active
- && c==' '
- && n>M_DIR_RP_LIMIT
- && t_param_1(term_do_n_ic,n)
- && (s=t_param_1(term_do_n_dc,n))
- )
- { if (n<screen.w) tputs(s,1,outchar);
- tputs(t_param_1(term_do_n_ic,n),1,outchar);
- return(n);
- }
- else
- do
- oputc(c);
- while (--n);
- }
-
- return(0);
- }
- /*}}} */
- /*{{{ init_terminal*/
- public void init_terminal(void)
- {
- if (term_do_ti)
- tputs(term_do_ti,1,outchar);
- switch (kp_state)
- { case 'A':
- case 'a':
- default:
- if (term_do_ks)
- { tputs(term_do_ks,1,outchar);
- fflush(stdout);
- }
- case 'N':
- case 'n':
- break;
- }
- }
- /*}}} */
- /*{{{ reset_terminal*/
- public void reset_terminal(void)
- {
- move_cursor_to(screen.h,1);
- oputc('\n');
- switch (kp_state)
- { case 'A':
- case 'a':
- default:
- if (term_do_ke)
- { tputs(term_do_ke,1,outchar);
- fflush(stdout);
- }
- case 'N':
- case 'n':
- break;
- }
- if (term_do_te) tputs(term_do_te,1,outchar);
- fflush(stdout);
- }
- /*}}} */
- /*{{{ do_standout*/
- public void do_standout(void)
- {
- if (so)
- { so_wished=True;
- if (scrout)
- { so_active=True;
- tputs(so,1,outchar);
- }
- }
- }
- /*}}} */
- /*{{{ do_standend*/
- public void do_standend(void)
- {
- if (term_do_se)
- { so_wished=False;
- if (scrout)
- { so_active=False;
- tputs(term_do_se,1,outchar);
- }
- }
- }
- /*}}} */
- /*{{{ moveclreol*/
- public void moveclreol(int y,int x)
- { if (scrout)
- { move_cursor_to(y,x);
- if (ce)
- tputs(ce,1,outchar);
- else
- { if (am && (y==screen.h)) x++;
- moputc(' ',screen.w-x);
- }
- }
- }
- /*}}} */
- /*{{{ clrscr*/
- public void ClrScr(void)
- {
- if (scrout)
- if (term_do_cl)
- tputs(term_do_cl,1,outchar);
- else if (term_do_ho && term_do_cd)
- /*{{{ home and clear to end of display*/
- { tputs(term_do_ho,1,outchar);
- tputs(term_do_cd,screen.h,outchar);
- }
- /*}}} */
- else
- /*{{{ clear line by line*/
- { int i;
-
- for (i=1;i<=screen.h;moveclreol(i++,1));
- if (am) outchar(' ');
- }
- /*}}} */
- }
- /*}}} */
- /*{{{ bell_audible*/
- public void bell_audible(void)
- {
- if (term_do_bl && scrout)
- { tputs(term_do_bl,1,outchar);
- fflush(scrout);
- }
- }
- /*}}} */
- /*{{{ bell_visible*/
- public void bell_visible(void)
- {
- if (term_do_vb && scrout)
- { tputs(term_do_vb,1,outchar);
- fflush(scrout);
- }
- }
- /*}}} */
- /*{{{ send_terminal*/
- public void send_terminal(int c)
- {
- putc(c,stdout);
- }
- /*}}} */
- /*{{{ flush_terminal*/
- public void flush_terminal(void)
- {
- fflush(stdout);
- }
- /*}}} */
- /*{{{ check_terminal*/
- public boolean check_terminal(char const * const t)
- {
- int l;
- boolean ok;
-
- ok=False;
- if (t[l=(strlen(t)-1)]=='*')
- { if (!strncmp(terminal,t,l-1)) ok=True; }
- else
- { if (!strcmp(terminal,t)) ok=True; }
-
- return(ok);
- }
- /*}}} */
- /*{{{ screen_off*/
- public void screen_off(void)
- { scrout=0;
- }
- /*}}} */
- /*{{{ screen_on*/
- public void screen_on(void)
- {
- scrout=stdout;
- if (so_wished!=so_active) if (so_wished) do_standout(); else do_standend();
- }
- /*}}} */
- /*{{{ get_terminal_capability*/
- #if (defined(MOUSY) && defined(XTERM))
- /*{{{ xterm_size*/
- private boolean xterm_size(char const * const t)
- {
- if (!strcmp(t,XTERM_MOUSE_NAME) && isatty(fileno(stdout)))
- /*{{{ try to get from xterm*/
- for (;;)
- { char b[32];
- char *d,*s;
-
- /*{{{ activate the sending*/
- fputs(XTERM_GET_SIZE,stdout);
- fflush(stdout);
- /*}}} */
- /*{{{ read the header*/
- s=XTERM_SIZE_HEAD;
- while (*s && (read_err(kbd_file,b),b[0]==*s)) s++;
- if (*s) break;
- /*}}} */
- /*{{{ get lines*/
- d=b;
- while (isdigit((read_err(kbd_file,d),*d++)));
- if (*--d!=XTERM_SIZE_MID[0]) break;
- *d=0;
- screen.h=atoi(b);
- /*}}} */
- /*{{{ get rest of mid text*/
- s=XTERM_SIZE_MID+1;
- while (*s && (read_err(kbd_file,b),b[0]==*s)) s++;
- /*}}} */
- /*{{{ get columns*/
- d=b;
- while (isdigit((read_err(kbd_file,d),*d++)));
- if (*--d!=XTERM_SIZE_END[0]) break;
- *d=0;
- screen.w=atoi(b);
- /*}}} */
- /*{{{ get rest of end text*/
- s=XTERM_SIZE_END+1;
- while (*s && (read_err(kbd_file,b),b[0]==*s)) s++;
- /*}}} */
- return(False);
- }
- /*}}} */
- return(True);
- }
- /*}}} */
- # define no_xterm_size xterm_size(terminal)
- #else
- # define no_xterm_size 1
- #endif
-
- public int get_terminal_capability(void)
- {
- /*{{{ terminal data variables*/
- # ifdef TIOCGWINSZ
- int res;
- struct winsize winsz;
- # endif
- # ifdef TERMINFO
- int result;
- # define GET_TERM_STR(cap,info) info
- # define GET_TERM_VAL(cap,info) info
- # define GET_TERM_TAG(cap,info) info
- # define GET_DATABASE(term) (setupterm(term,2,&result),resetterm(),result)
- # define INIT_DATABASE()
- # else
- static char termcap_area[512];
- static char bp[1024];
- static char *pointer;
- # define GET_TERM_STR(cap,info) tgetstr(cap,&pointer)
- # define GET_TERM_VAL(cap,info) tgetnum(cap)
- # define GET_TERM_TAG(cap,info) tgetflag(cap)
- # define GET_DATABASE(term) tgetent(bp,term)
- # define INIT_DATABASE() pointer=termcap_area
- # endif
- /*}}} */
-
- if (!terminal)
- /*{{{ first call => get terminal dependent strings*/
- {
- /*{{{ get terminal name*/
- if (!(terminal=getenv(TERM)))
- # ifdef DEFAULT_TERM
- terminal=DEFAULT_TERM;
- # else
- { oputs((char *)get_msg(M_NO_TERM));
- return(1);
- }
- # endif
- /*}}} */
- /*{{{ read termcap data*/
- switch (GET_DATABASE(terminal))
- { case -1: { oputs((char *)get_msg(F_NO_TERMCAP,TERM_DATA_BASE));return (1); }
- case 0: { oputs((char *)get_msg(F_TERMB,terminal,TERM_DATA_BASE));return (1); }
- }
- INIT_DATABASE();
- /*}}} */
- /*{{{ get needed features*/
- /*{{{ cursor motion*/
- /*{{{ cursor move*/
- term_do_cm=GET_TERM_STR("cm",cursor_address);
- /*}}} */
- /*{{{ home*/
- term_do_ho=GET_TERM_STR("ho",cursor_home);
- /*}}} */
- /*{{{ down*/
- term_do_do=GET_TERM_STR("do",cursor_down);
- /*}}} */
- /*{{{ down**/
- term_do_n_do=GET_TERM_STR("DO",parm_down_cursor);
- /*}}} */
- /*{{{ right*/
- term_do_ri=GET_TERM_STR("nd",cursor_right);
- /*}}} */
- /*{{{ right**/
- term_do_n_ri=GET_TERM_STR("RI",parm_right_cursor);
- /*}}} */
- if (!term_do_cm && !(term_do_ho && (term_do_do || term_do_n_do) && (term_do_ri || term_do_n_ri)))
- { oputs((char *)get_msg(F_TERMA,"cursor motion (cm)",terminal));
- exit(r_init_err);
- }
- /*}}} */
- /*{{{ screen size*/
- # ifdef TIOCGWINSZ
- if (ioctl(0,TIOCGWINSZ,&winsz)!=-1)
- { screen.h=winsz.ws_row;
- screen.w=winsz.ws_col;
- }
- # endif
- if (screen.h<=0)
- screen.h=GET_TERM_VAL("li",lines);
- if (screen.w<=0)
- screen.w=GET_TERM_VAL("co",columns);
- if (screen.h<=0 || screen.w<=0)
- { oputs((char *)get_msg(F_TERMA,STR_WINSIZE,terminal));
- exit(r_init_err);
- }
- /*}}} */
- /*}}} */
- /*{{{ get optional features*/
- /*{{{ init/reset terminal*/
- term_do_ti=GET_TERM_STR("ti",enter_ca_mode);
- term_do_te=GET_TERM_STR("te",exit_ca_mode);
- /*}}} */
- /*{{{ clear's*/
- ce=GET_TERM_STR("ce",clr_eol);
- term_do_cl=GET_TERM_STR("cl",clear_screen);
- term_do_cd=GET_TERM_STR("cd",clr_eos);
- /*}}} */
- /*{{{ add/delete line*/
- al=GET_TERM_STR("al",insert_line);
- do_AL=GET_TERM_STR("AL",parm_insert_line);
- dl=GET_TERM_STR("dl",delete_line);
- do_DL=GET_TERM_STR("DL",parm_delete_line);
- /*}}} */
- /*{{{ bells*/
- term_do_bl=GET_TERM_STR("bl",bell);
- term_do_vb=GET_TERM_STR("vb",flash_screen);
- /*}}} */
- /*{{{ keypad*/
- term_do_ks=GET_TERM_STR("ks",keypad_xmit);
- term_do_ke=GET_TERM_STR("ke",keypad_local);
- /*}}} */
- /*{{{ standout*/
- /*{{{ get standout glitches*/
- if ((sg=GET_TERM_VAL("sg",magic_cookie_glitch))==-1)
- sg=0;
- xs=GET_TERM_TAG("xs",ceol_standout_glitch);
- xt=GET_TERM_TAG("xt",teleray_glitch);
- # ifdef USE_SCRBUFF
- # ifndef BLOCK_FLUSH
- mi=GET_TERM_TAG("mi",move_insert_mode);
- # endif
- # endif
- /*}}} */
- if
- (
- # ifndef USE_SCRBUFF
- xt || xs ||
- # endif
- ( ( !(so=GET_TERM_STR("so",enter_standout_mode))
- || !(term_do_se=GET_TERM_STR("se",exit_standout_mode))
- )
- && ( !(so=GET_TERM_STR("mr",enter_reverse_mode))
- || !(term_do_se=GET_TERM_STR("me",exit_attribute_mode))
- )
- && ( !(so=GET_TERM_STR("us",enter_underline_mode))
- || !(term_do_se=GET_TERM_STR("ue",exit_underline_mode))
- )
- )
- )
- so=term_do_se=0;
- /*}}} */
- /*{{{ repeat character*/
- term_do_rp=GET_TERM_STR("rp",repeat_char);
- /*}}} */
- /*{{{ cursor*/
- # ifdef USE_SCRBUFF
- term_do_vi=GET_TERM_STR("vi",cursor_invisible);
- term_do_vs=GET_TERM_STR("vs",cursor_visible);
- if (term_do_vi && !term_do_vs)
- term_do_vs=GET_TERM_STR("ve",cursor_normal);
- else if (!term_do_vi && term_do_vs)
- term_do_vi=GET_TERM_STR("ve",cursor_normal);
- if (!term_do_vs)
- term_do_vi=0;
- else if (!term_do_vi)
- term_do_vs=0;
- # endif
- /*}}} */
- # if defined(USE_SCRBUFF) && !defined(BLOCK_FLUSH)
- /*{{{ additional cursor movements*/
- term_do_up=GET_TERM_STR("up",cursor_up);
- term_do_n_up=GET_TERM_STR("UP",parm_up_cursor);
- term_do_le=GET_TERM_STR("le",cursor_left);
- term_do_LE=GET_TERM_STR("LE",parm_left_cursor);
- /*}}} */
- # endif
- if (!GET_TERM_TAG("in",insert_null_glitch))
- /*{{{ read insert/delete character stuff*/
- { term_do_n_ic=GET_TERM_STR("IC",parm_ich);
- term_do_n_dc=GET_TERM_STR("DC",parm_dch);
- # if defined(USE_SCRBUFF) && !defined(BLOCK_FLUSH)
- term_do_im=GET_TERM_STR("im",enter_insert_mode);
- term_do_ic=GET_TERM_STR("ic",insert_character);
- term_do_ip=GET_TERM_STR("ip",insert_padding);
- term_do_ei=GET_TERM_STR("ei",exit_insert_mode);
- term_do_dc=GET_TERM_STR("dc",delete_character);
- # endif
- }
- /*}}} */
- /*}}} */
- /*{{{ check some strange features*/
- # if defined(USE_SCRBUFF) && !defined(BLOCK_FLUSH)
- use_shift=False;
- if ((term_do_im || term_do_ic) && (term_do_dc || term_do_n_dc) && !xs)
- use_shift=True;
- # endif
- am=GET_TERM_TAG("am",auto_right_margin);
- hz=GET_TERM_TAG("hz",tilde_glitch);
- /*}}} */
- }
- /*}}} */
- else
- /*{{{ get window-size*/
- { if (no_xterm_size)
- {
- # ifdef TIOCGWINSZ
- res=ioctl(0,TIOCGWINSZ,&winsz);
- screen.h=(res==-1 || winsz.ws_row<=0)
- ? GET_TERM_VAL("li",lines)
- : winsz.ws_row;
- screen.w=(res==-1 || winsz.ws_col<=0)
- ? GET_TERM_VAL("co",columns)
- : winsz.ws_col;
- # else
- screen.h=GET_TERM_VAL("li",lines);
- screen.w=GET_TERM_VAL("co",columns);
- # endif
- }
- }
- /*}}} */
- /*{{{ minimum window is 1x1*/
- if (screen.h<=0)
- screen.h=1;
- if (screen.w<=0)
- screen.w=1;
- /*}}} */
- return (0);
- }
- /*}}} */
-